import pyautogui
from desktopmagic.screengrab_win32 import (getDisplayRects, getRectAsImage)
import time
import xlrd
import cv2
import numpy as np

# 获取副屏的位置
screens = getDisplayRects()  # 获取所有屏幕
def find_image_on_screen(template_path, threshold=0.96):
    # 读取模板图片
    template = cv2.imread(template_path)
    template_height, template_width = template.shape[:2]
    # 截取整个屏幕
    rect = getRectAsImage(screens[1])
    # 保存截图
    rect.save('test.png')
    screen = cv2.imread("test.png")
    # 模板匹配
    result = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED)
    locations = np.where(result >= threshold)
    matches = []
    for pt in zip(*locations[::-1]):
        matches.append({
            'left': pt[0],
            'top': pt[1],
            'width': template_width,
            'height': template_height,
            'confidence': result[pt[1], pt[0]]
        })
    matches.sort(key=lambda x: x['confidence'], reverse=True)
    return matches
# 定义副屏鼠标事件
def fClick(clickTimes, lOrR, img, speed):
    # 查找图片
    matches = find_image_on_screen(img)
    if not matches:
        raise Exception("找不到图片!!!")
    else:
        # 使用最佳匹配
        best_match = matches[0]
        # 计算图片中心位置
        center_x = best_match['left'] + best_match['width'] // 2 + x
        center_y = best_match['top'] + best_match['height'] // 2 + y
        pyautogui.moveTo(center_x, center_y, duration=speed)
        pyautogui.click(clicks=clickTimes, duration=speed, button=lOrR)
    time.sleep(0.1)

# 定义鼠标事件
def mouseClick(clickTimes, lOrR, img, reTry, speed):
    if reTry == 1:  # 只重复一次
        while True:
            location = pyautogui.locateCenterOnScreen(img, confidence=mohu)  # 获取图片的位置
            if location is not None:
                pyautogui.moveTo(location.x, location.y, duration=speed)
                pyautogui.click(clicks=clickTimes, interval=0.2, duration=0.2, button=lOrR)
                break
            time.sleep(0.1)
    elif reTry == -1:
        while True:
            location = pyautogui.locateCenterOnScreen(img, confidence=mohu)
            if location is not None:
                pyautogui.moveTo(location.x, location.y, duration=speed)
                pyautogui.click(clicks=clickTimes, interval=0.2, duration=0.2, button=lOrR)
            time.sleep(0.1)
    elif reTry > 1:
        i = 1
        while i < reTry + 1:
            location = pyautogui.locateCenterOnScreen(img, confidence=mohu)
            if location is not None:
                pyautogui.moveTo(location.x, location.y, duration=speed)
                pyautogui.click(clicks=clickTimes, interval=0.2, duration=0.2, button=lOrR)
                print("重复")
                i += 1
            time.sleep(0.1)


# 数据检查
# cmdType.value  1.0 左键单击    2.0 左键双击  3.0 右键单击  4.0 输入  5.0 等待  6.0 滚轮 7 8
# ctype属性值含义：
#           空：0
#           字符串：1
#           数字：2
#           日期：3
#           布尔：4
#           error：5
def dataCheck(sheet1):
    checkCmd = True
    # 行数检查
    if sheet1.nrows < 2:
        print("文件cmd.xls暂无数据")
        checkCmd = False
    # 每行数据检查
    i = 1
    while i < sheet1.nrows:  # 便利出每一行
        # 第1列 操作类型检查
        cmdType = sheet1.row(i)[0]  # 获取表1的第i行第1列数据
        '''判断浮点数是否为合理的数
        if cmdType.ctype != 2 or (cmdType.value != 1.0 and cmdType.value != 2.0 and cmdType.value != 3.0 
        and cmdType.value != 4.0 and cmdType.value != 5.0 and cmdType.value != 6.0):
        '''  # 用map将遍历的整型转化为浮点型
        if cmdType.ctype != 2 or (cmdType.value not in map(float, range(1, 8))):  # 不在1.0-7.0内时
            print('第', i + 1, "行,第1列数据 应在1,2,3,4,5,6，7数字范围内")
            checkCmd = False
        # 第2列 内容检查
        cmdValue = sheet1.row(i)[1]
        # 读图点击类型指令，内容必须为字符串类型
        if cmdType.value in map(float, range(1, 4)):  # 第一列的值是否在1.0-3.0
            if cmdValue.ctype != 1:
                print('第', i + 1, "行,第2列数据 只能是文件名.后缀名的字符串")
                checkCmd = False
        # 输入类型，内容不能为空
        if cmdType.value == 4.0:
            if cmdValue.ctype == 0:
                print('第', i + 1, "行,第2列数据 不能为空")
                checkCmd = False
        # 等待类型，内容必须为数字
        if cmdType.value == 5.0:
            if cmdValue.ctype != 2:
                print(cmdValue.ctype)
                print('第', i + 1, "行,第2列数据 只能是数字")
                checkCmd = False
        # 滚轮事件，内容必须为数字
        if cmdType.value == 6.0:
            if cmdValue.ctype != 2:
                print('第', i + 1, "行,第2列数据 只能是数字（上正，下负）")
                checkCmd = False
        # ctrl事件，内容必须为字母
        if cmdType.value == 6.0:
            if cmdValue not in ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
                                'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']:
                print('第', i + 1, "行,第2列数据 只能是字母")
                checkCmd = False
        i += 1  # 下一行
    return checkCmd


# 任务
def mainWork(img):
    i = 1
    while i < sheet1.nrows:  # 遍历sheet表的每一行
        # 取本行指令的操作类型
        cmdType = sheet1.row(i)[0]
        # 代表带年纪左键
        if cmdType.value == 1.0:
            # 取图片名称
            img = sheet1.row(i)[1].value
            print(fp == 0)
            if fp == 0:
                reTry = 1
                if sheet1.row(i)[2].ctype == 2 and sheet1.row(i)[2].value != 0:  # 重复值是否为大于零的数字
                    reTry = sheet1.row(i)[2].value
                mouseClick(1, "left", img, reTry, 0.1)  # 单机次数，
            else:fClick(1, "left", img, 0.1)  # 单机次数，
            print("单击左键", img)
        # 2代表双击左键
        elif cmdType.value == 2.0:
            # 取图片名称
            img = sheet1.row(i)[1].value
            # 取重试次数
            reTry = 1
            if sheet1.row(i)[2].ctype == 2 and sheet1.row(i)[2].value != 0:
                reTry = sheet1.row(i)[2].value
            mouseClick(2, "left", img, reTry, 0.1)
            print("双击左键", img)
        # 3代表右键
        elif cmdType.value == 3.0:
            # 取图片名称
            img = sheet1.row(i)[1].value
            # 取重试次数
            reTry = 1
            if sheet1.row(i)[2].ctype == 2 and sheet1.row(i)[2].value != 0:
                reTry = sheet1.row(i)[2].value
            mouseClick(1, "right", img, reTry, 0.1)
            print("右键", img)
            # 4代表输入
        elif cmdType.value == 4.0:
            inputValue = sheet1.row(i)[1].value
            pyautogui.write(inputValue)
            time.sleep(0.5)
            print("输入:", inputValue)
            # 5代表等待
        elif cmdType.value == 5.0:
            # 取图片名称
            waitTime = sheet1.row(i)[1].value
            time.sleep(waitTime)
            print("等待", waitTime, "秒")
        # 6代表滚轮
        elif cmdType.value == 6.0:
            # 取图片名称
            scroll = sheet1.row(i)[1].value
            pyautogui.scroll(int(scroll))
            print("滚轮滑动", int(scroll), "距离")
        # 7代表ctrl+
        elif cmdType.value == 7.0:
            # 取图片名称
            key = sheet1.row(i)[1].value
            pyautogui.hotkey('ctrl', key)
            print("ctrl + ", key)
        i += 1


def init():
    global mohu, x, y, fp
    mohu = sheet1.row(1)[3].value
    fp = sheet1.row(1)[4].value
    x = sheet1.row(2)[4].value
    y = sheet1.row(3)[4].value


if __name__ == '__main__':
    file = 'cmd.xls'  # 通过相对路径获取文件
    # 打开文件
    # xlrd模块：对excel中的数据读取
    wb = xlrd.open_workbook(filename=file)  # 此时wb已将数据加载到内存当中
    # 通过索引获取表格sheet页
    sheet1 = wb.sheet_by_index(0)  # 打开第一个sheet表，并用变量sheet1引用此表单
    init()
    # 数据检查
    checkCmd = dataCheck(sheet1)  # 调用上方自定义函数，判断是否合理，返回boolean类型参数
    if checkCmd:
        while True:
            print("运行中..")
            mainWork(sheet1)  # 调用调用上方自定义函数，进行操作
            a = pyautogui.confirm(text='是否还要继续', title='提示', buttons=[True, False])
            if not eval(a):
                print("退出")
                break
    else:
        print('输入有误或者已经退出!')
